package com.baidu.fsg.uid.config;

import cn.hutool.core.util.StrUtil;
import com.baidu.fsg.uid.IdMappingService;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.json.UTF8StreamJsonParser;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import javax.annotation.Resource;
import java.io.IOException;

@Configuration
public class JacksonConfiguration {

    @Resource
    IdMappingService idMappingService;

    @Bean
    @Primary
    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(String.class,new JsonSerializer<String>(){

            @Override
            public void serialize(String value, JsonGenerator gen, SerializerProvider provider) throws IOException {

                String fieldName = gen.getOutputContext().getCurrentName();
                if("id".equals(fieldName)){
                    gen.writeString(value);
                    if(IdMappingDisableConfiguration.isDisable.get() != null && IdMappingDisableConfiguration.isDisable.get()){
                        return;
                    }
                    String uuid = idMappingService.getUUID(value);
                    if(StrUtil.isEmpty(uuid)){
                        return;
                    }
                    gen.writeStringField("uuid", uuid);
                    return;
                }
                if(StrUtil.isEmpty(fieldName)){
                    gen.writeString(value);
                    return;
                }
                if(fieldName.endsWith("_idToUuid")){
                    if(IdMappingDisableConfiguration.isDisable.get() != null && IdMappingDisableConfiguration.isDisable.get()){
                        gen.writeString(value);
                        return;
                    }
                    String uuid = idMappingService.getUUID(value);
                    if(StrUtil.isEmpty(uuid)){
                        gen.writeNull();
                        return;
                    }
                    gen.writeString(uuid);
                    return;
                }
                if(fieldName.endsWith("_uuidToId")){
                    if(IdMappingDisableConfiguration.isDisable.get() != null && IdMappingDisableConfiguration.isDisable.get()){
                        gen.writeString(value);
                        return;
                    }
                    String id = idMappingService.getId(value);
                    if(StrUtil.isEmpty(id)){
                        gen.writeNull();
                        return;
                    }
                    gen.writeString(id);
                    return;
                }
                gen.writeString(value);
            }
        });
        simpleModule.addDeserializer(String.class, new JsonDeserializer(){

            @Override
            public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
                if(!(p instanceof UTF8StreamJsonParser)){
                    return "";
                }
                UTF8StreamJsonParser utf8StreamJsonParser = (UTF8StreamJsonParser) p;
                utf8StreamJsonParser.finishToken();
                String value = utf8StreamJsonParser.getText();
                if("uuidToId".equals(p.getCurrentName())){
                    if(IdMappingDisableConfiguration.isDisable.get() != null && IdMappingDisableConfiguration.isDisable.get()){
                        return value;
                    }
                    String id = idMappingService.getId(value);
                    if(StrUtil.isEmpty(id)){
                        return null;
                    }
                    return id;
                }
                if(StrUtil.isEmpty(p.getCurrentName())){
                    return value;
                }
                if(p.getCurrentName().endsWith("_uuidToId")){
                    if(IdMappingDisableConfiguration.isDisable.get() != null && IdMappingDisableConfiguration.isDisable.get()){
                        return value;
                    }
                    String id = idMappingService.getId(value);
                    if(StrUtil.isEmpty(id)){
                        return null;
                    }
                    return id;
                }
                if(p.getCurrentName().endsWith("_idToUuid")){
                    if(IdMappingDisableConfiguration.isDisable.get() != null && IdMappingDisableConfiguration.isDisable.get()){
                        return value;
                    }
                    String uuid = idMappingService.getUUID(value);
                    if(StrUtil.isEmpty(uuid)){
                        return null;
                    }
                    return uuid;
                }
                return value;
            }
        });
        objectMapper.registerModule(simpleModule);
        return objectMapper;
    }
}